package com.scs.application.modules.upms.listener;

import com.scs.application.core.permission.Button;
import com.scs.application.core.permission.Resource;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.upms.consts.DictConsts;
import com.scs.application.modules.upms.entity.Menu;
import com.scs.application.modules.upms.service.MenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.util.StopWatch;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description: 初始化按钮权限数据到数据库中
 */
@Slf4j
//@Component
public class InitButtonDataListener implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private MenuService menuService;


    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {

        String displayName = event.getApplicationContext().getDisplayName();
        if (displayName.contains("zipkin") || displayName.startsWith("FeignContext")) {
            return;
        }

        StopWatch stopWatch = new StopWatch();
        log.info("准备初始化按钮权限定义");
        stopWatch.start();

        // 开始加载按钮权限定义
        Map<Resource, List<Button>> buttonMap = Maps.newHashMap();

        Map<String, Object> map = event.getApplicationContext().getBeansWithAnnotation(Resource.class);

        for (String beanName : map.keySet()) {
            List<Button> buttons = Lists.newArrayList();

            Class<?> realClass = AopUtils.getTargetClass(map.get(beanName));
            Method[] methods = realClass.getDeclaredMethods();

            for (Method method : methods) {
                Button button = method.getDeclaredAnnotation(Button.class);
                if (button == null) {
                    continue;
                }
                buttons.add(button);
            }
            if (buttons.size() != 0) {
                buttonMap.put(realClass.getDeclaredAnnotation(Resource.class), buttons);
            }
        }
        if (buttonMap.size() == 0) {
            stopWatch.stop();
            log.info("初始化按钮权限定义完成,共保存{}个资源、{}个按钮定义,耗时：{}秒", buttonMap.size(), buttonMap.values().size(), stopWatch.getTotalTimeSeconds());
            return;
        }

        // 获取所有菜单数据
        List<Menu> menus = menuService.list();

        // 将code放到map中，避免每次都遍历所有菜单
        final String type = DictConsts.MENU_TYPE_BUTTON;
        Map<String, Menu> menuCodeMap = menus.stream().filter(o -> !StringUtils.isBlank(o.getCode()) && !type.equals(o.getType()))
                .collect(Collectors.toMap(o -> o.getCode(), a -> a, (k1, k2) -> k1));
        Map<String, Menu> permissionMap = menus.stream().filter(o -> !StringUtils.isBlank(o.getPermissions()) && type.equals(o.getType()))
                .collect(Collectors.toMap(o -> o.getPermissions(), a -> a, (k1, k2) -> k1));

        List<Menu> addedMenus = Lists.newArrayListWithCapacity(buttonMap.values().size());
        for (Resource resource : buttonMap.keySet()) {
            Menu menu = menuCodeMap.get(resource.code());
            if (menu == null) {
                log.debug("资源[{}]-[{}]未添加，不保存按钮定义", resource.code(), resource.name());
                continue;
            }

            List<Button> buttons = buttonMap.get(resource);
            for (Button button : buttons) {
                // 未找到相同标识的
                Menu tmp = permissionMap.get(button.permission());
                if (tmp == null) {
                    tmp = new Menu();
                }
                tmp.setType(type).setIsShow(0).setName(button.name())
                        .setPermissions(button.permission()).setSort((long) button.sort())
                        .setParentId(menu.getId()).setParentIds(menu.getParentIds() + menu.getId() + ",")
                ;
                addedMenus.add(tmp);
            }
        }
        if (!addedMenus.isEmpty()) {
            menuService.saveOrUpdateBatch(addedMenus);
        }

        stopWatch.stop();
        log.info("初始化按钮权限定义完成,共保存{}个资源、{}个按钮定义,耗时：{}秒", buttonMap.size(), addedMenus.size(), stopWatch.getTotalTimeSeconds());
    }
}
